<template>
<div class="commodity-class-treeview">
    <div v-if="showHeader" style="position: relative;height:24px;font-size:12px;">
        <div style="position:absolute;height:100%;width:200%;margin-left:-100%;background-color:#eee;wdith:100%;"></div>
        <div class="tree-item">
            <span style="margin-left:-20px;">分类名称</span>
            <span class="tree-item-buttons" v-if="operateable">
                <span v-if="sortable" class="sort-buttons">排序</span>
                <span class="operation-buttons">操作</span>
                <span class="add-buttons">添加子类</span>
            </span>
            <div class="long-line"></div>
        </div>
    </div>
    <Tree v-if="showTree" :ref="treeId" :data="treeData" :render="renderContent"></Tree>
</div>
</template>
<script>
    export default {
        props: {
            defaultSelectedValues: {
                type: Array,
                default: () => []
            },
            model: {
                type: Object,
                default: () => { return {} }
            },
            prop: {
                type: String,
                default: 'values'
            },
            data: {
                type: Array,
                default: () => []
            },
            operateable: {
                type: Boolean,
                default: true
            },
            sortable: {
                type: Boolean,
                default: true
            },
            selectable: {
                type: Boolean,
                default: true
            },
            showHeader: {
                type: Boolean,
                default: true
            },
            maxLevel: {
                type: Number,
                default: 10
            },
            justShowSelectedNode: {
                type: Boolean,
                default: false
            }
        },
        data () {
            return {
                treeId: "treeview" + Date.now(),
                nodes: [],
                showTree: true
            }
        },
        computed: {
            treeData() {
                if(this.justShowSelectedNode) {
                    return this.getSelectedTree(this.nodes);
                }else {
                    return this.nodes;
                }
            }
        },
        methods: {
            renderContent (h, { root, node, data }) {
                var appendStr = '';
                if(!this.operateable && data.children && data.children.length > 0) {
                    // 如果有必要显示选择了多少子节点
                    var count = data.children.filter(elem => elem.selected || elem.indeterminate).length;
                    appendStr = ` (${count})`;
                }

                return h("span", { class: { 'tree-item': true } }, [
                    this.selectable ? h("Checkbox", { 
                        props: { 
                            value: node.node.selected,
                            indeterminate: node.node.indeterminate
                        },
                        on: {
                            'on-change': value => {
                                this.handleSelect(value, data, node, root);
                            } 
                        }
                    }, node.node.title + appendStr) : h("span", {  }, node.node.title + appendStr),

                    this.operateable ? h("span", { class: { 'tree-item-buttons': true } }, [
                        this.sortable ? h("span", { class: { 'sort-buttons': true } }, [
                            h("Button", { style: { padding: "0 2px" }, props: { type: "text", size: "small", icon: "md-arrow-round-back", disabled: !this.sortable || data.isStatic || data.level == 1 }, on: {
                                click: () => {
                                    this.handleEmit('on-left-click', root, node, data);
                                }
                            } }),
                            h("Button", { style: { padding: "0 2px" }, props: { type: "text", size: "small", icon: "md-arrow-round-forward", disabled: !this.sortable || data.isStatic || data.level == this.maxLevel }, on: {
                                click: () => {
                                    this.handleEmit('on-right-click', root, node, data);
                                }
                            } }),
                            h("Button", { style: { padding: "0 2px" }, props: { type: "text", size: "small", icon: "md-arrow-round-up", disabled: !this.sortable || data.isStatic }, on: {
                                click: () => {
                                    this.handleEmit('on-up-click', root, node, data);
                                }
                            } }),
                            h("Button", { style: { padding: "0 2px" }, props: { type: "text", size: "small", icon: "md-arrow-round-down", disabled: !this.sortable || data.isStatic }, on: {
                                click: () => {
                                    this.handleEmit('on-down-click', root, node, data);
                                }
                            } }),
                        ]) : h("span"),
                        h("span", { class: { 'operation-buttons': true } }, [
                            h("Button", { props: { type: "text", size: "small", disabled: data.isStatic }, on: {
                                click: () => {
                                    this.handleEmit('on-edit-click', root, node, data);
                                }
                            } }, "编辑"),
                            h("Button", { props: { type: "text", size: "small", disabled: data.isStatic }, on: {
                                click: () => {
                                    this.handleEmit('on-delete-click', root, node, data);
                                }
                            } }, "删除"),
                        ]),
                        h("span", { class: { 'add-buttons': true } }, [
                            h("Button", { props: { type: "text", size: "small", icon: "md-add", disabled: data.level >= this.maxLevel }, on: {
                                click: () => {
                                    this.handleEmit('on-add-click', root, node, data);
                                }
                            } }),
                        ]),
                    ]) : h("span"),
                    h("div", { class: { 'long-line': true } })
                ]);
            },
            handleSelect(value, data, node, root) {
                // this.showTree = false;
                this.doSelect(value, data, node, root, true, true);
                var values = this.getSelectedValues();
                var simpleValues = this.getSelectedSimpleValues();
                var titles = this.getSelectedTitles();
                this.model[this.prop] = values;
                this.$emit("on-select", values, simpleValues, titles, this);
                // this.showTree = true;
            },
            doSelect(value, data, node, root, canChangeChildren, canChangeParent) {
                if(canChangeChildren) {
                    // 说明是被点击的节点或者子节点，它的indeterminate状态很容易确定
                    node.node.selected = value;
                    node.node.indeterminate = false;

                }else if(!canChangeChildren && canChangeParent) {
                    // 说明是被点击节点的父级，需要判断
                    var count = node.node.children.filter(elem => elem.selected == value).length;

                    if(value) {
                        if(count == node.node.children.length) {
                            //this.$set(node.node, 'selected', true);
                            node.node.selected = true;
                        }
                    }else {
                        node.node.selected = false;
                    }
                    
                    node.node.indeterminate = this.isIndeterminate(node.node);
                }
                
                if(canChangeParent) {
                    var parent = root[node.parent];
                    if(parent) {
                        this.doSelect(value, parent.node, parent, root, false, true);
                    }
                }

                if(canChangeChildren && node.node.children && node.node.children.length > 0) {
                    node.node.children.forEach(elem => this.doSelect(value, elem, root[elem.nodeKey], root, true, false) );
                }
            },
            getSelectedTree(arrayData) {
                var temp = [];
                arrayData.forEach(elem => {
                    if(elem.indeterminate || elem.selected) {
                        var children = elem.children ? this.getSelectedTree(elem.children) : [];
                        temp.push({
                            value: elem.value,
                            title: elem.title,
                            selected: elem.selected,
                            indeterminate: elem.indeterminate,
                            children: children
                        });
                    }
                });
                return temp;
            },
            isIndeterminate(item) {
                var count = item.children.filter(elem => elem.selected).length;
                var indeterminateCount = item.children.filter(elem => elem.indeterminate).length;
                if((count > 0 && count < item.children.length) || indeterminateCount > 0) {
                    return true;
                }else {
                    return false;
                }
            },
            formatData(data, parent) {
                // this.showTree = false;
                if(!parent) {
                    parent = {
                        values: '',
                        titles: '',
                        level: 0
                    }
                }

                var nodes = [];
                data.forEach(elem => {
                    nodes.push(this.formatDataChild(elem, parent));
                });

                // this.showTree = true;

                return nodes;
            },
            formatDataChild(child, parent) {
                if(!parent) {
                    parent = {
                        values: '',
                        titles: '',
                        level: 0
                    }
                }
                // this.showTree = false;
                var node = Object.assign({}, child);
                if(child.value) {
                    this.$set(node, "values", `${parent.values}[${child.value}]`);
                    this.$set(node, "titles", `${parent.titles}${parent.titles.length?'-':''}${child.title}`);
                    this.$set(node, "level", parent.level + 1);
                    this.$set(node, "selected", false);
                    this.$set(node, "indeterminate", false);

                    if(child.children) {
                        node.children = this.formatData(child.children, node);
                    }

                    if(this.defaultSelectedValues.indexOf(node.values) != -1) {
                        node.selected = true;
                    }

                    node.indeterminate = this.isIndeterminate(node);
                }else {
                    console.warn(`产品分类项${child.title}未提供value值`);
                }
                // this.showTree = true;
                return node;
            },
            getMinSelectedNodes(data, container) {
                container = container || [];
                data = data || this.treeData;
                data.forEach(elem => {
                    if(elem.selected) {
                        container.push(elem);
                    }else if(elem.children){
                        this.getMinSelectedNodes(elem.children, container);
                    }
                });
                return container;
            },
            getMaxSelectedNodes() {
                return this.$refs[this.treeId].getSelectedNodes();
            },
            nodesMapToValues(nodes) {
                return nodes.map(elem => elem.values);
            },
            nodesMapToSimpleValues(nodes) {
                return nodes.map(elem => `[${elem.value}]`);
            },
            nodesMapToTitles(nodes) {
                return nodes.map(elem => elem.titles);
            },
            getSelectedValues() {
                // 为了容易匹配，值是获取所有打勾的项，所以用max
                var temp = this.getMaxSelectedNodes();
                var values = this.nodesMapToValues(temp);
                return values;
            },
            getSelectedSimpleValues() {
                // 为了容易匹配，值是获取所有打勾的项，所以用max
                var temp = this.getMaxSelectedNodes();
                var values = this.nodesMapToSimpleValues(temp);
                return values;
            },
            getSelectedTitles() {
                // title是显示时用的，所以越简洁越好，所以用min
                var temp = this.getMinSelectedNodes();
                var titles = this.nodesMapToTitles(temp);
                return titles;
            },
            clearSelect(items) {
                // this.showTree = false;
                if(!items) items = this.nodes;
                items.forEach(elem => {
                    if(elem.children) {
                        this.clearSelect(elem.children);
                    }
                    elem.selected = false;
                    elem.indeterminate = false;
                });
                // this.showTree = true;
            },
            handleEmit(eventName, root, node, data) {
                
                var parent, index;
                var parentKey = root.find(el => el === node).parent;
                var temp = root.find(el => el.nodeKey === parentKey);

                if(temp) {
                    parent = temp.node;
                    index = parent.children.indexOf(data);
                }else {
                    parent = {
                        values: '',
                        titles: '',
                        level: 0,
                        children: this.treeData
                    };
                    index = this.treeData.indexOf(data);
                }

                var callback;
                switch(eventName) {
                    case 'on-add-click': callback = (item) => {
                        if(!item.children) {
                            item.children = [];
                        }
                        data.children.push(this.formatDataChild(item, data));
                    }; break;
                    case 'on-edit-click': callback = (item) => {
                        data.title = item.title;
                        this.formatDataChild(data, parent);
                    }; break;
                    case 'on-delete-click': callback = () => {
                        parent.children.splice(index, 1);
                    }; break;
                    case 'on-up-click': callback = () => {
                        if(index > 0) {
                            this.$set(parent.children, index, parent.children[index-1]);
                            this.$set(parent.children, index-1, data);
                        }
                    }; break;
                    case 'on-down-click': callback = () => {
                        if(index < parent.children.length - 1) {
                            this.$set(parent.children, index, parent.children[index+1]);
                            this.$set(parent.children, index+1, data);
                        }
                    }; break;
                    case 'on-right-click': callback = () => {
                        if(index > 0) {
                            var prev = parent.children[index-1];
                            parent.children.splice(index, 1);
                            prev.children.push(data);
                        }
                    }; break;
                    case 'on-left-click': callback = () => {
                        if(data.level > 1) {
                            var parentChildren;
                            if(data.level == 2) {
                                parentChildren = this.treeData;
                            }else {
                                var parentKey = root.find(el => el.node == parent).parent;
                                var temp = root.find(el => el.nodeKey === parentKey);
                                if(temp) {
                                    parentChildren = temp.node.children;
                                }
                            }
                            if(parentChildren) {
                                parent.children.splice(index, 1);
                                parentChildren.push(data);
                            }
                        }
                    }; break;
                }

                this.$emit(eventName, data, parent, index, callback);
            },
            refreshNodes() {
                this.nodes = this.formatData(this.data);
                this.$emit('on-refresh', this);

            },
        },
        watch: {
            data() {
                this.refreshNodes();
            },
            defaultSelectedValues(values) {
                this.refreshNodes();
            }
        },
        created() {
            this.refreshNodes();
        }
    }
</script>
<style lang="less">
.commodity-class-treeview {
    position: relative;
    border: 1px solid #ddd;
    border-bottom: 0;
    overflow: hidden;
    padding-left: 5px;
    .tree-item {
        position: absolute;
        top: 0;
        right: -20px;
        display: inline-block;
        width: 100%;
        height: 24px;
        line-height: 24px;
        /*&::before {
            content: "";
            position: absolute;
            bottom: 12px;
            right: 0;
            width: 200%;
            z-index: 0;
            height: 100%;
            border-bottom: 1px solid #ddd;
        }*/
        &:hover {
            background-color: rgb(233, 242, 247);
        }
        &-buttons {
            text-align: center;
            float: right;
            height: 100%;
            margin: 0;
            padding-right: 20px;
            .sort-buttons {
                display: inline-block;
                border-left: 1px solid #ddd;
                width: 100px;
                height: 24px;
                line-height: 24px;
            }
            .operation-buttons {
                display: inline-block;
                border-left: 1px solid #ddd;
                width: 100px;
                height: 24px;
                line-height: 24px;
            }
            .add-buttons {
                display: inline-block;
                border-left: 1px solid #ddd;
                width: 75px;
                height: 24px;
                line-height: 24px;
            }
        }
        .long-line {
            position: absolute;
            bottom: 1px;
            right: 0;
            width: 200%;
            border-bottom: 1px solid #ddd;
        }
    }
}
.commodity-class-treeview .ivu-tree ul li {
    position: relative;
    min-height: 24px;
    line-height: 24px;
    margin: 0;
}
</style>

